home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
modula.zoo
/
_defn_ex_process.mod
< prev
next >
Wrap
Text File
|
1988-04-26
|
14KB
|
345 lines
IMPLEMENTATION MODULE Process[7];
FROM SYSTEM IMPORT
ADDRESS, WORD, BYTE, REG, SETREG, ADR, TSIZE, VAL, INLINE;
(*FROM InOut IMPORT
WriteString, WriteLn, WriteLongHex, Read;
*)
CONST
ModuleBase = 12;
ProcessBase = 13;
FramPointer = 14;
StackPointer = 15;
CONST
InitialStatus = M68000StatusRegister{sbIntMask0, sbIntMask1};
(* Special for ATARI: all Processes are running on Interrupt Level 3 *)
MinimumStackSize = 256; (* ??? *)
TYPE
InitialStack =
RECORD
Context : M68000Context;
SavedReturnPC : PROC;
END; (* InitialStack *)
PROCEDURE LISTEN;
(*
LISTEN: move.w sr,d0
trap #11 * switch to supervisormode
move.w #$0300,sr * interrupt allowed, usermode
nop
nop
trap #11
move.w d0,sr * restore old SR
*)
BEGIN
INLINE( 040C0H,04E4BH,046FCH,00300H,04E71H,04E71H,04E4BH,046C0H );
END LISTEN;
PROCEDURE CoRoutineEnd();
BEGIN
(* This Procedure is never called directly. An illegally terminating
process will enter this procedure loading a return address from its
stack, which has been saved there by NEWPROCESS
*)
IF MainPROCESSPtr <> NIL THEN
TRANSFER( ErrorPROCESS, MainPROCESSPtr^ );
ELSE HALT; END;
END CoRoutineEnd;
PROCEDURE NEWPROCESS (ProcessCode : PROC;
WorkSpaceBase : ADDRESS;
WorkSpaceSize : LONGCARD;
VAR ProcessDesc : PROCESS );
TYPE
InitialStackPointer = POINTER TO InitialStack;
LongIntPtr = POINTER TO LONGINT;
VAR
InitialStackPtr : InitialStackPointer;
WorkSpacePtr,
WorkSpaceEnd : LongIntPtr;
savemask : CARDINAL;
BEGIN
(* Check process workspace *)
IF ODD( WorkSpaceBase ) THEN HALT; END;
IF WorkSpaceSize < VAL( LONGCARD, MinimumStackSize ) THEN HALT; END;
IF ProcessDesc = NIL THEN (* Clear workspace for size and access test *)
WorkSpacePtr := VAL( LongIntPtr, WorkSpaceBase );
WorkSpaceEnd :=
VAL( LongIntPtr, VAL( LONGCARD, WorkSpaceBase )
+ WorkSpaceSize
- VAL( LONGCARD, 3 ) );
WHILE VAL( LONGCARD, WorkSpacePtr ) < VAL( LONGCARD, WorkSpaceEnd ) DO
WorkSpacePtr^ := 0;
INC( VAL( LONGINT, WorkSpacePtr ), 4 );
END; (* FOR *)
END; (* IF *)
InitialStackPtr := VAL( InitialStackPointer,
VAL( LONGCARD, WorkSpaceBase)
+ WorkSpaceSize
- VAL( LONGCARD, TSIZE(InitialStack))
);
WITH InitialStackPtr^ DO
WITH Context DO
ModuleBaseA4 := REG(ModuleBase);
(* ProcessBase auf das obere Ende, (MODEP-Process-Descriptor) *)
Valid := NIL; (*DS*)
ProcessBaseA5 := WorkSpaceBase+VAL(ADDRESS,WorkSpaceSize); (*DS*)
FramePointerA6 := NIL;
StackPointerA7 := NIL;
StatusRegister := InitialStatus;
ProgramCounter := ProcessCode;
END; (* WITH *)
SavedReturnPC := CoRoutineEnd;
END; (* WITH *)
ProcessDesc := VAL( PROCESS, InitialStackPtr );
END NEWPROCESS;
PROCEDURE InstallTrap();
(* Calling this Routine installs all Assembler routines *)
(*
*
* - der SUPERVISORMODE ist nicht erlaubt (in MODEB nicht nötig)
*
* dadurch ergibt sich daß TRANSFER,IOTRANSFER nur vom Usermode aufgerufen
* werden. Beim INT muß ein Unterscheidung sttatfinden und beim Übergangen
* S -> U der USP bzw. bei U -> S der SSP gerettet werden. Der letzter Fall
* kommt aber eigentlich nie vor. Sämtliche load's speicheren den zusätzs-
* lichen Stackpointer gegebenenfalls zurück.
trap3 = $8c * TRANSFER
trap4 = $90 * IOTRANSFER
call = $4eb9
stop_int = $46fc2700
magic = $04091964
INIT: move.w sr,d0 * save old mode
trap #11 * Supervisormode
lea TRANSFER-*-2(pc),a0
move.l a0,trap3
lea IOTRANSFER-*-2(pc),a0
move.l a0,trap4
move.w d0,sr * now old mode again
bra exit
* in Usermode:
*
* (A0) USP -> ^To.l (A1)
* ^From.l (A2)
* :
*
* SSP -> Sr.w (D0)
* Pc.l
* :
* only A4,A5,A6 must be saved !
TRANSFER: move.w #$2700,sr * no interrupt allowed
move.w (a7)+,d0 * get SR
utrans: move.l usp,a0 * get USP
move.l (a0)+,a1 * pointer to "to"
move.l (a0),a2 * pointer to "from", USP now clean
move.l (a7)+,(a0) * PC, SSP now clean
move.w d0,-(a0) * SR
clr.l -(a0) * Stack=NIL
movem.l a4-a6,-(a0) * save important registers
lea -$30(a0),a0 * rest of registers
move.l #magic,-(a0) * MAGIC setzen
move.l a0,usp * set new USP
move.l (a1),a6 * load "to"
move.l a0,(a2) * save "from"
btst.b #5,$44(a6) * new process in supervisormode ?
bne sload
uload: lea $4a(a6),a0 * top of context
move.l a0,usp * set new USP to "to"
move.l $40(a6),d1 * get stack
beq ul_nil * NIL, don't load
move.l d1,a7 * load SSP
ul_nil: move.l -(a0),-(a7) * PC
move.w -(a0),-(a7) * SR
clr.l (a6)+ * MAGIC löschen
movem.l (a6)+,d0-a5 * restore registers
move.l (a6),a6 * A6
rte
sload: move.l a6,a7 * set new SSP to "to"
move.l $40(a7),d1 * get stack
beq sl_nil * NIL, don't load
move.l d1,a1
move.l a1,usp * load USP
sl_nil: clr.l (a7)+ * MAGIC löschen
movem.l (a7)+,d0-a6 * restore registers
tst.l (a7)+ * discharge stack
rte
* in Usermode:
*
* (A0) USP -> Vector.l (A1)
* ^To.l (A2)
* ^From.l (A3)
* :
*
* SSP -> Sr.w (D0)
* Pc.l
* :
IOTRANSFER: move.w #$2700,sr * no interrupt allowed
move.w (a7)+,d0 * get SR
uiotrans: move.l usp,a0 * get USP
movem.l (a0)+,a1-a3 * clean up USP
move.l (a7)+,-(a0) * PC, SSP now clean
move.w d0,-(a0) * SR
clr.l -(a0) * stack=NIL
movem.l a4-a6,-(a0) * save important registers
move.l a2,-(a0) * A3: Pointer to "to"
lea -$2c(a0),a0 * rest of registers
move.l #magic,-(a0) * MAGIC setzen
move.l (a2),a6 * load "to"
move.l a0,(a3) * save "from"
lea INT-*-2(pc),a2 * interrupt routine
move.l a2,-(a0) * push
move.w #call,-(a0) * push JSR opcode
move.l #stop_int,-(a0) * push MOVE.W #$2700,SR opcode
move.l a0,(a1) * set vector
move.l a0,usp * set new USP
btst.b #5,$44(a6) * new proces